import Foundation

// 构造过程


/// 1. 存储属性有默认值
/// 2. 未提供自定义构造器
/// 所以会获得一个默认构造器
class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "\(numberOfWheels) wheel(s)"
    }
}

public func initialzieDemo_1() {
    let vehicle = Vehicle()
    print("Vehicle: \(vehicle.description)")
    // Vehicle: 0 wheel(s)
}


class Bicycle: Vehicle {
    override init() {
        // 第一阶段
        super.init()
        // 第二阶段
        numberOfWheels = 2
    }
}

// MARK: - 构造器的继承重写

/// 1. 子类的构造器没有在第二段中作自定义操作,
/// 2. 父类有一个同步, 无参数的构造器
/// 就可以`省略super.init`的调用
class Hoverboard: Vehicle {
    var color: String
    init(color: String) {
        self.color = color
        // super.init() 在这里被隐式调用
    }
    
    override var description: String {
        return "\(super.description) in a beautiful \(color)"
    }
}

public func initialzieDemo_2() {
    let hoverboard = Hoverboard(color: "silver")
    print("Hoverboard: \(hoverboard.description)")
    // Hoverboard: 0 wheel(s) in a beautiful silver
}



// MARK: - 构造器的自动继承
/// 子类默认不继承父类构造器, 如果想继承需要满足以下两点:
/// 1. 子类`没有任何指定构造器`, 会自动继承所有指定构造器
/// 2. 如果子类提供了`所有父类指定构造器的实现`, 它将继承父类的`所有便利构造器`

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

let namedMeat = Food(name: "Bacon")
// namedMeat 的名字是 "Bacon"
let mysteryMeat = Food()
// mysteryMeat 的名字是 [Unnamed]


class RecipeIngredient: Food {
    var quantity: Int
    
    // 自定义的指定构造器
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    
    // 1. 实现父类的指定构造器_1
    convenience override init(name: String) {
        self.init(name: name, quantity: 1)
    }
    
    // 2. 就能继承父类的便利构造器
    
//    override init(name: String) {
//        self.quantity = 1
//        super.init(name: name)
//    }
}


// MARK: - 可失败构造器
struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty {
            return nil
        }
        self.species = species
    }
}

public func initialzieDemo_3() {
    let someCreature = Animal(species: "Giraffe")
    if let giraffe = someCreature {
        print("An animal was initialized with a species of \(giraffe.species)")
    }
}


